#include "device.h"
//昂瑞微的驱动库API
#include "rwip_config.h" // RW SW configuration
#include "peripheral.h"
#include "pin.h"

#define PWM_COUNT_FREQ   2000000
#define PWM_PERIOD_COUNT 100

// 电机RF PWM通道
#define MOTO_R_PWM_CHANNAL TIM_PWM_CHANNEL_0 // PWM通道号
#define MOTO_F_PWM_CHANNAL TIM_PWM_CHANNEL_1

#define MOTO_R_PULSE_COUNT 0 // 占空比 = MOTO_R_PULSE_COUNT / PWM_PERIOD_COUNT
#define MOTO_F_PULSE_COUNT 0

void tim_pwm_handler(void);

#if defined(MOTOR_R_PIN) && defined(MOTOR_F_PIN)
static void PWM_Motor_Init(void);
#endif

const tim_config_t pwm_cfg =
    {
        .mode = TIM_PWM_MODE,
        .config.pwm =
        {
            // pwm_frequency = count_freq/period_count (2000Hz)
            .count_freq = 20000,    
            .period_count = 5,      //重载值
            .channel =
            {
                // duty cycle = pulse_count/period_count
                {true/*enable*/, {TIM_PWM_POL_HIGH2LOW, 1}}, // channel0: duty cycle = 1/5
                {false/*enable*/, {TIM_PWM_POL_HIGH2LOW, 2}}, // channel1: duty cycle = 2/5
                {false/*enable*/, {TIM_PWM_POL_HIGH2LOW, 3}}, // channel2: duty cycle = 3/5
                {false/*enable*/, {TIM_PWM_POL_HIGH2LOW, 4}}, // channel3: duty cycle = 4/5
            },
            .callback = NULL,
        },
    };

    tim_config_t moto_pwm_cfg =
    {
        .mode = TIM_PWM_MODE,
        .config.pwm =
        {
            // pwm_frequency = count_freq/period_count (2000Hz)
            .count_freq = 10000,
            .period_count = 10,
            .channel =
            {
                // duty cycle = pulse_count/period_count
                {false/*enable*/, {TIM_PWM_POL_HIGH2LOW, 1}}, // channel0: duty cycle = 1/5
                {false/*enable*/, {TIM_PWM_POL_HIGH2LOW, 2}}, // channel1: duty cycle = 2/5
                {false/*enable*/, {TIM_PWM_POL_HIGH2LOW, 3}}, // channel2: duty cycle = 3/5
                {false/*enable*/, {TIM_PWM_POL_HIGH2LOW, 4}}, // channel3: duty cycle = 4/5
            },
            .callback = tim_pwm_handler,
        },
    };

/**
  * @brief  使能PWM
  * @note   
  * 
  * @param  dev：虚拟设备
  * @return 成功/失败
  */
static int8_t PWM_Enable(VirtualHardware_enum_t dev)
{
    tim_init();
    if(dev == vPWM_0)
    {
        #ifdef BUZZER_PIN
        printf("pwm en\r\n");
        pinmux_config(BUZZER_PIN, PINMUX_TIMER1_IO_0_CFG);

        tim_config(HS_TIM1, &pwm_cfg);
        
        tim_start(HS_TIM1);
        #endif
    }
    else if(dev == vPWM_1)
    {
#if defined(MOTOR_R_PIN) && defined(MOTOR_F_PIN)
	#ifndef MOTO_USER_IO
        PWM_Motor_Init();
        tim_start(HS_TIM1);
			  tim_pwm_channel_force_output(HS_TIM1,MOTO_R_PWM_CHANNAL,TIM_PWM_FORCE_DISABLE);
        tim_pwm_channel_force_output(HS_TIM1,MOTO_F_PWM_CHANNAL,TIM_PWM_FORCE_DISABLE);
	#endif
#endif
    }
    else if(dev == vPWM_2)
    {

    }

}


/**
  * @brief  失能PWM
  * @note   
  * 
  * @param  dev：虚拟设备
  * @return 成功/失败
  */
static int8_t PWM_Disable(VirtualHardware_enum_t dev)
{
    if(dev == vPWM_0)
    {
        #ifdef BUZZER_PIN
        printf("pwm dis\r\n");
        tim_stop(HS_TIM1);
        pinmux_config(BUZZER_PIN, PINMUX_GPIO_MODE_CFG);
        pmu_pin_mode_set(BITMASK(BUZZER_PIN), PMU_PIN_MODE_PP);
        gpio_write(BITMASK(BUZZER_PIN), GPIO_LOW);
        gpio_set_direction(BITMASK(BUZZER_PIN), GPIO_OUTPUT);
#endif
    }
    else if(dev == vPWM_1)
    {
        #ifdef MOTO_IN1
        tim_stop(HS_TIM0);
        pinmux_config(MOTO_IN1, PINMUX_GPIO_MODE_CFG);
        pmu_pin_mode_set(BITMASK(MOTO_IN1), PMU_PIN_MODE_PP);
        gpio_write(BITMASK(MOTO_IN1), GPIO_LOW);
        gpio_set_direction(BITMASK(MOTO_IN1), GPIO_OUTPUT);
        #endif
			
        #if defined(MOTOR_R_PIN) && defined(MOTOR_F_PIN)
            #ifndef MOTO_USER_IO
                    tim_stop(HS_TIM1);
                    tim_pwm_channel_force_output(HS_TIM1,MOTO_R_PWM_CHANNAL,TIM_PWM_FORCE_LOW);//
                    tim_pwm_channel_force_output(HS_TIM1,MOTO_F_PWM_CHANNAL,TIM_PWM_FORCE_LOW);//
            #endif
        #endif
    }
    else if(dev == vPWM_2)
    {
        #ifdef MOTO_IN2
        tim_stop(HS_TIM0);
        pinmux_config(MOTO_IN2, PINMUX_GPIO_MODE_CFG);
        pmu_pin_mode_set(BITMASK(MOTO_IN2), PMU_PIN_MODE_PP);
        gpio_write(BITMASK(MOTO_IN2), GPIO_LOW);
        gpio_set_direction(BITMASK(MOTO_IN2), GPIO_OUTPUT);
        #endif
			
        #if defined(MOTOR_R_PIN) && defined(MOTOR_F_PIN)
            #ifndef MOTO_USER_IO
                    tim_stop(HS_TIM1);
                    tim_pwm_channel_force_output(HS_TIM1,MOTO_R_PWM_CHANNAL,TIM_PWM_FORCE_LOW);//
                    tim_pwm_channel_force_output(HS_TIM1,MOTO_F_PWM_CHANNAL,TIM_PWM_FORCE_LOW);//
            #endif
        #endif
    }

}
uint32_t num = 0;
/**
 * @brief tim_pwm_handler()
 *
 * @return 
 **/
void tim_pwm_handler(void)
{
    static uint8_t duty;
    num++;
    if(num > 40)
    {
        num = 0;
        if(moto_pwm_cfg.config.pwm.channel[0].enable == true)
        {
            if(moto_pwm_cfg.config.pwm.channel[0].config.pulse_count++ < 10)
            {
                tim_stop(HS_TIM0);
                tim_config(HS_TIM0, &moto_pwm_cfg);
                tim_start(HS_TIM0);
            }
        }
        else if(moto_pwm_cfg.config.pwm.channel[1].enable == true)
        {
            if(moto_pwm_cfg.config.pwm.channel[1].config.pulse_count++ < 10)
            {
                tim_stop(HS_TIM0);
                tim_config(HS_TIM0, &moto_pwm_cfg);
                tim_start(HS_TIM0);
            }
        }
    }
}

/**
  * @brief  设置PWM参数
  * @note   
  * 
  * @param  dev：虚拟设备
  * @param  frequency：pwm频率（单位：HZ）
  * @param  duty_cycle：pwm占空比（范围：0.00 ~ 100.00）
  * @return 成功/失败
  */
static int8_t PWM_SetPwm(VirtualHardware_enum_t dev, uint32_t frequency, float duty_cycle)
{
//    if (dev == vPWM_1 || dev == vPWM_2)
//    {
//        if((duty_cycle > 0)&&(duty_cycle < 100))
//        {
//            tim_stop(HS_TIM0);

//            #ifdef MOTO_IN1
//            pinmux_config(MOTO_IN1, PINMUX_TIMER0_IO_0_CFG);
//            #endif

//            #ifdef MOTO_IN2
//            pinmux_config(MOTO_IN2, PINMUX_TIMER0_IO_1_CFG);
//            #endif

//            num = 0;
//            if(dev == vPWM_1)
//            {
//                moto_pwm_cfg.config.pwm.channel[0].enable = true;
//                moto_pwm_cfg.config.pwm.channel[1].enable = false;
//                moto_pwm_cfg.config.pwm.channel[0].config.pulse_count = duty_cycle/10;
//                moto_pwm_cfg.config.pwm.channel[1].config.pulse_count = 0;
//            }
//            else if(dev == vPWM_2)
//            {
//                moto_pwm_cfg.config.pwm.channel[0].enable = false;
//                moto_pwm_cfg.config.pwm.channel[1].enable = true;
//                moto_pwm_cfg.config.pwm.channel[0].config.pulse_count = 0;
//                moto_pwm_cfg.config.pwm.channel[1].config.pulse_count = duty_cycle/10;
//            }
//            tim_config(HS_TIM0, &moto_pwm_cfg);
//            tim_start(HS_TIM0);
//        }
//        else if(duty_cycle == 100)
//        {
//            if(dev == vPWM_1)
//            {
//                #ifdef MOTO_IN1
//                tim_stop(HS_TIM0);
//                pinmux_config(MOTO_IN1, PINMUX_GPIO_MODE_CFG);
//                pmu_pin_mode_set(BITMASK(MOTO_IN1), PMU_PIN_MODE_PP);
//                gpio_write(BITMASK(MOTO_IN1), GPIO_HIGH);
//                gpio_set_direction(BITMASK(MOTO_IN1), GPIO_OUTPUT);
//                #endif
//            }
//            else if(dev == vPWM_2)
//            {
//                #ifdef MOTO_IN2
//                tim_stop(HS_TIM0);
//                pinmux_config(MOTO_IN2, PINMUX_GPIO_MODE_CFG);
//                pmu_pin_mode_set(BITMASK(MOTO_IN2), PMU_PIN_MODE_PP);
//                gpio_write(BITMASK(MOTO_IN2), GPIO_HIGH);
//                gpio_set_direction(BITMASK(MOTO_IN2), GPIO_OUTPUT);
//                #endif
//            }            
//        }
//        else        //0
//        {
//            if(dev == vPWM_1)
//            {
//                moto_pwm_cfg.config.pwm.channel[0].enable = true;
//                moto_pwm_cfg.config.pwm.channel[0].config.pulse_count = 0;
//            }
//            else if(dev == vPWM_2)
//            {
//                moto_pwm_cfg.config.pwm.channel[1].enable = true;
//                moto_pwm_cfg.config.pwm.channel[1].config.pulse_count = 0;
//            }
//            tim_config(HS_TIM0, &moto_pwm_cfg);
//        }
//    }
	
		  if (dev == vPWM_1)
			{
	#ifndef MOTO_USER_IO
					tim_pwm_channel_change_pulse_count(HS_TIM1, MOTO_R_PWM_CHANNAL, (uint16_t)duty_cycle);
	#endif
			}
			else if (dev == vPWM_2)
			{
	#ifndef MOTO_USER_IO
					tim_pwm_channel_change_pulse_count(HS_TIM1, MOTO_F_PWM_CHANNAL, (uint16_t)duty_cycle);
	#endif
			}
			else
			{
					return -1;
			}

    return 0;
}

/**
  * @brief  PWM定时器初始化
  * @note   
  */
static void pwmHal_Init(void)
{
    tim_init();

#ifdef BUZZER_PIN
    pinmux_config(BUZZER_PIN, PINMUX_GPIO_MODE_CFG);
    pmu_pin_mode_set(BITMASK(BUZZER_PIN), PMU_PIN_MODE_PP);
    gpio_write(BITMASK(BUZZER_PIN), GPIO_LOW);
    gpio_set_direction(BITMASK(BUZZER_PIN), GPIO_OUTPUT);
#endif
}



/**
 * @brief  PWM端口配置
 * @note
 */
static void PWM_IO_Init(void)
{
    /* 电机控制脚配置
        R：PWM通道0
        F：PWM通道1
    */
#ifdef MOTO_USER_IO
    HS_PIN_FUNC_SET(MOTOR_F_PIN, PINMUX_GPIO_MODE_CFG);
    HS_PIN_MODE_SET(MOTOR_F_PIN, PMU_PIN_MODE_PP);
    HS_GPIO_DIR_SET(MOTOR_F_PIN, GPIO_OUTPUT);
    HS_GPIO_WRITE(MOTOR_F_PIN, GPIO_LOW);

    HS_PIN_FUNC_SET(MOTOR_R_PIN, PINMUX_GPIO_MODE_CFG);
    HS_PIN_MODE_SET(MOTOR_R_PIN, PMU_PIN_MODE_PP);
    HS_GPIO_DIR_SET(MOTOR_R_PIN, GPIO_OUTPUT);
    HS_GPIO_WRITE(MOTOR_R_PIN, GPIO_LOW);
#else
#ifdef MOTOR_R_PIN
    HS_PIN_FUNC_SET(MOTOR_R_PIN, PINMUX_TIMER1_IO_0_CFG);
    HS_PIN_MODE_SET(MOTOR_R_PIN, PMU_PIN_MODE_PP);
#endif
#ifdef MOTOR_F_PIN
    HS_PIN_FUNC_SET(MOTOR_F_PIN, PINMUX_TIMER1_IO_1_CFG);
    HS_PIN_MODE_SET(MOTOR_F_PIN, PMU_PIN_MODE_PP);
#endif
#endif
}

/**
 * @brief tim1_pwm_handler()
 *
 * @return
 **/
static void tim1_pwm_handler(void)//50us  
{
    HS_TIM1->SR = 0;
    Device_IRQHandler(vPWM_1, NULL, 0);
}

/**
 * @brief  PWM定时器初始化
 * @note
 */
static void PWM_Motor_Init(void)
{
    const tim_config_t pwm_cfg =
    {
        .mode = TIM_PWM_MODE,
        .config.pwm =
        {
            // pwm_frequency =/period_count (20kHz)
            .count_freq = PWM_COUNT_FREQ,
            .period_count = PWM_PERIOD_COUNT,
            .channel =
            {
                // duty cycle = pulse_count/period_count 占空比初始化时为 0
                {true/*enable*/, {TIM_PWM_POL_HIGH2LOW, MOTO_R_PULSE_COUNT}}, // channel0
                {true/*enable*/, {TIM_PWM_POL_HIGH2LOW, MOTO_F_PULSE_COUNT}}, // channel1
            },
            .callback = tim1_pwm_handler,
        },
    };

    // PWM Init
    tim_init();
    tim_config(HS_TIM1, &pwm_cfg);
    // tim_start(HS_TIM1);
}

/**
  * @brief  PWM初始化
  * @note   
  */
static void PWM_Init(void)
{
    uint32_t times = 0;
    printf("pwm init\r\n");
    /* 1、初始化硬件 */
		//pwmHal_Init();
		PWM_IO_Init();
#ifndef MOTO_USER_IO
    PWM_Motor_Init();
#endif
    /* 2、将底层设备具体操作接口，挂到设备控制块里面 */
    Device_stu_t *dcb  = Device_GetDeviceCtrlBlock(vPWM);
    dcb->enable = PWM_Enable;
    dcb->disable = PWM_Disable;
    dcb->set_pwm = PWM_SetPwm;
		
#ifndef MOTO_USER_IO      
    PWM_Disable(vPWM_0);
	PWM_Disable(vPWM_1);
#endif      
    

    // PWM_Enable(vPWM_1);
    // PWM_Enable(vPWM_2);

    // PWM_SetPwm(vPWM_2,0,0);    
    // PWM_SetPwm(vPWM_1,0,20);
    // co_delay_ms(500);

    // PWM_SetPwm(vPWM_1,0,0);    
    // PWM_SetPwm(vPWM_2,0,20);
    // co_delay_ms(500);
    // PWM_Disable(vPWM_1);
    // PWM_Disable(vPWM_2);
    // while(1)
    // {
    //     times++;
    //     if(times == 20)
    //     {
    //         PWM_SetPwm(vPWM_2,0,20);
    //         printf("pwm2\r\n");
    //     }
    //     else if(times == 30)
    //     {
    //         PWM_SetPwm(vPWM_2,0,0);
    //         printf("pwm3\r\n");
    //     }
        // rwip_schedule();
    //     co_delay_ms(200);
    //     printf("code is run\r\n");
    // }
}
INIT_DEVICE_EXPORT(PWM_Init);